<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数据分析</title>
    <link rel="stylesheet" href="./css/elemet.css">
    <script src="./js/vue.js"></script>
    <script src="./js/echarts.js"></script>
    <script src="./js/element.js"></script>
    <script src="./js/moment.js"></script>
</head>
<style>
    /deep/ .el-input__inner {
        background-color: #003e00;
        color: #fff;
        border: 1px solid #e43179;
    }

    /* 改变滚动条的颜色 */
    * {
        scrollbar-width: thin;
        scrollbar-color: #2D315D #F5F5F5;
    }
    *::-webkit-scrollbar {
        background-color: #F5F5F5;
        width: 10px;
    }
    *::-webkit-scrollbar-thumb {
        background-color: #2D315D;
        border-radius: 5px;
    }

    /* 改变滚动条被悬停时的颜色 */
    *::-webkit-scrollbar-thumb:hover {
        background-color: #666;
    }

    /* 改变滚动条的轨道宽度和颜色 */
    *::-webkit-scrollbar-track {
        background-color: #F5F5F5;
        border-radius: 5px;
    }

    html, body, #app {
        width: 100%;
        height: 100%;
        margin: 0px;
        padding: 0px;
        background-color: #202344;
    }

    .top {
        position: relative;
    }

    .top img {
        width: 100%;
        height: 88px;
    }

    .top .title {
        position: absolute;
        left: 50%;
        top: 19px;
        transform: translateX(-50%);
        font-size: 40px;
        font-weight: 700;
        color: #ffffff;
    }

    .filter {
        display: flex;
        justify-content: flex-end;
        padding: 0 40px;
        margin-top: 39px;
    }

    .filter .select {
        margin-right: 16px;
    }

    .selectColor {
        background-color: #202344;
        color: #ffffff;
    }

    .filter .tab {
        display: flex;
    }

    .filter .tab .tab_item {
        display: flex;
        width: 48px;
        height: 32px;
        background-color: #2D315D;
        color: #ffffff;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
    }

    .filter .tab .active {
        background-color: #8D8BA8;
    }

    .filter .daterange {
        margin-left: 16px;
    }

    .filter .month {
        margin-left: 16px;
    }

    .menu {
        display: flex;
        justify-content: space-between;
        margin-top: 24px;
        padding: 0 40px;
    }

    .menu .menu_item {
        width: 23%;
        height: 180px;
        background-color: #2D315D;
        display: flex;
        align-items: center;
        padding-left: 28px;
    }

    .menu .menu_item img {
        width: 100px;
        height: 100px;
    }

    .menu .menu_item .text {
        margin-left: 24px;
        color: #ffffff;
    }

    .menu .menu_item .text .label {
        font-size: 24px;
        margin-bottom: 25px;
    }

    .content {
        margin-top: 24px;
        padding: 0 40px 40px;
    }

    .content .wrap {
        padding-top: 50px;
        background-color: #2D315D;
    }
    .content .wrap:nth-child(2) {
        margin-top: 30px;
    }

    .content .wrap #echart {
        width: 100%;
    }

    .content .wrap #lineEchart {
        width: 100%;
    }
</style>
<body>
<div id="app">
    <div class="top">
        <img src="./img/ic_tb_bg.png" alt="">
        <div class="title">量化交易可视化</div>
    </div>
    <div class="filter">
        <el-select class="select" v-model="selectValueOne" placeholder="请选择" size="mini" popper-class="selectColor"
                   @change="handleOneChange">
            <el-option
                    v-for="item in selectOptionOne"
                    :key="item.key"
                    :label="item.label"
                    :value="item.key"
            >
            </el-option>
        </el-select>
        <el-select class="select" v-model="selectValueTwo" placeholder="请选择面板类型" size="mini"
                   popper-class="selectColor"
                   @change="handleTwoChange">
            <el-option
                    v-for="item in selectOptionTwo"
                    :key="item.key"
                    :label="item.label"
                    :value="item.key"
            >
            </el-option>
        </el-select>
        <el-select class="select" v-model="selectValueThree" placeholder="请选择账号或模型" size="mini"
                   popper-class="selectColor" multiple collapse-tags @change="handleThreeChange">
            <el-option
                    v-for="item in selectOptionThree"
                    :key="item.key"
                    :label="item.label"
                    :value="item.key"
            >
            </el-option>
        </el-select>
        <!-- 时间tab选择-->
        <div class="tab">
            <div v-for="(item,index) in tabConfig"
                 :key="index"
                 class="tab_item"
                 :class="item.key === activeTab ? 'active': ''"
                 @click="handleTabChange(item)"
            >
                {{item.label}}
            </div>
        </div>
        <el-date-picker
                v-if="activeTab === 1"
                class="daterange"
                v-model="value1"
                type="daterange"
                size="mini"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="yyyy-MM-dd HH:mm:ss"
                @change="handleRangeChange"
        >
        </el-date-picker>
        <el-date-picker
                v-if="activeTab === 2"
                class="month"
                v-model="value2"
                size="mini"
                type="monthrange"
                range-separator="至"
                start-placeholder="开始月份"
                end-placeholder="结束月份"
                value-format="yyyy-MM-dd HH:mm:ss"
                @change="handleMonthChange"
        >
        </el-date-picker>
    </div>
    <div class="menu">
        <div class="menu_item" v-for="(item,index) in menuConfig" :key="index">
            <img :src="item.icon" alt="">
            <div class="text">
                <div class="label">{{item.label}}</div>
                <div class="value" :title="totalData[item.key]">
                    <el-statistic
                            :value-style="{fontSize: '35px', fontWeight: '500',color: '#FFFFFF'}"
                            group-separator=","
                            :precision="2"
                            :value="totalData[item.key]"
                    ></el-statistic>
                </div>
            </div>
        </div>
    </div>
    <div class="content">
        <div class="wrap">
            <div id="echart" :style="{height: echartHeight + 'px'}"></div>
        </div>

        <div class="wrap">
            <div id="lineEchart" :style="{height: echartHeight + 'px'}"></div>
        </div>
    </div>
</div>
</body>
</html>

<script>
    var app = new Vue({
        el: '#app',
        data() {
            // 请求地址
            const baseurl = 'https://hk.hnshengzhong.cn/admin/'
            // 请求头信息
            const headers = {
                'Accept': 'application/json',
                'token': '4b23f1e5462cd941c5e310108f14871c'
            }
            // 菜单配置
            const menuConfig = [
                {label: '总权益', key: 'eq', icon: './img/总权益.gif'},
                {label: '总占用', key: 'frozen_bal', icon: './img/总占用.gif'},
                {label: '未实现盈亏', key: 'upl', icon: './img/未实现盈亏.gif'},
                {label: '总利润', key: 'profit', icon: './img/总利润.gif'},
            ]
            // 时间配置
            const tabConfig = [
                {label: '日', key: 1},
                {label: '月', key: 2},
            ]
            // select配置
            const selectOptionOne = [
                {label: '未实现收益', key: 'upl_data'},
                {label: '收益数据', key: 'profit_data'},
                {label: '回撤数据', key: 'ret_data'},
                {label: '资金数据', key: 'asset_data'},
            ]
            const selectOptionTwo = [
                {label: '账号', key: 1},
                {label: '模型', key: 2},
            ]
            // line 折线图颜色配置
            const color = [
                ['rgb(24, 144, 255)', 'rgba(24, 144, 255,0.2)'],
                ['rgb(216, 61, 108)', 'rgba(216, 61, 108,0.2)'],
                ["rgb(0, 199, 217)", "rgba(0, 199, 217,0.2)"],
                ["rgb(255, 157, 77)", "rgba(255, 157, 77,0.2)"],
                ["rgb(131, 58, 179)", "rgba(131, 58, 179,0.2)"],
                ["rgb(255, 153, 195)", "rgba(255, 153, 195,0.2)"],
                ["rgb(127, 178, 240)", "rgba(127, 178, 240,0.2)"],
                ["rgb(232, 104, 74)", "rgba(232, 104, 74,0.2)"],
                ["rgb(27, 188, 155)", "rgba(27, 188, 155,0.2)"],
                ["rgb(246, 189, 22)", "rgba(246, 189, 22,0.2)"],
                ["rgb(91, 143, 249)", "rgba(91, 143, 249,0.2)"],
                ["rgb(255, 77, 77)", "rgba(255, 77, 77,0.2)"],
                ["rgb(2, 203, 126)", "rgba(2, 203, 126,0.2)"],
                ["rgb(192, 118, 250)", "rgba(192, 118, 250,0.2)"],
                ["rgb(93, 112, 146)", "rgba(93, 112, 146,0.2)"],
                ["rgb(26, 160, 234)", "rgba(26, 160, 234,0.2)"],
                ["rgb(255, 193, 3)", "rgba(255, 193, 3,0.2)"],
                ["rgb(255, 97, 162)", "rgba(255, 97, 162, 0.2)"],
                ["rgb(255, 90, 51)", "rgba(255, 90, 51, 0.2)"],
                ["rgb(255, 48, 133)", "rgba(255, 48, 133, 0.2)"],
            ]
            // 折线图配置
            const option = {
                color: [],
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        label: {
                            backgroundColor: '#6a7985'
                        }
                    }
                },
                legend: {
                    textStyle: {
                        color: '#FFFFFF',
                        fontSize: '14'
                    },
                    icon: 'rect',
                    right: "5%",
                    data: []
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: [
                    {
                        type: 'category',
                        boundaryGap: false,
                        offset: 8.5,
                        data: [],
                        axisLabel: {
                            color: "#FFFFFF"
                        },
                    }
                ],
                yAxis: [
                    {
                        name: "单位",
                        type: 'value',
                        nameTextStyle: {
                            align: 'right',
                            color: "#FFFFFF",
                            fontSize: '16',
                            lineHeight: 70
                        },
                        axisLabel: {
                            color: "#FFFFFF"
                        },
                        splitLine: {
                            lineStyle: {
                                type: 'dashed'
                            }
                        },
                    }
                ],
                series: []
            }
            return {
                baseurl,
                headers,
                menuConfig,
                tabConfig,
                selectOptionOne,
                selectOptionTwo,
                option,
                color,
                selectOptionThree: [], // 账号or模型配置
                loading: '', // 全局loading
                allAccount: [], // 所有账号
                allModel: [], // 所有模型
                activeTab: 1, // 时间tab选中
                myChart: '', // echart
                lineEchart: '', //
                selectValueOne: 'profit_data', // 列选择器选中
                selectValueTwo: '',
                selectValueThree: [],
                start_date: '', // 开始时间
                end_date: '', // 结束时间
                value1: '', // 日选择器
                value2: '', // 月选择器
                ListData: {},// echart 数据
                echartHeight: 0, // echart 高度
                totalData: { // 总数统计
                    eq: 0,
                    frozen_bal: 0,
                    upl: 0,
                    profit: 0
                },
            }
        },
        created() {
            this.echartHeight = (document.body.clientHeight / 2) - 100
        },
        async mounted() {
            console.log(document.body.clientHeight)
            this.loading = this.$loading({
                lock: true,
                text: 'Loading',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)'
            })
            this.myChart = echarts.init(document.getElementById('echart'))
            this.lineEchart = echarts.init(document.getElementById('lineEchart'))
            await this.getAccountList()
            await this.getModelList()
            window.onresize = () => {
                this.myChart.resize()
                this.lineEchart.resize()
            }
        },
        methods: {
            /**
             * 获取可视化数据
             */
            async getPanelData() {
                this.loading = this.$loading({
                    lock: true,
                    text: 'Loading',
                    spinner: 'el-icon-loading',
                    background: 'rgba(0, 0, 0, 0.7)'
                })
                const params = {
                    panel_type: this.selectValueTwo,
                    date_range: this.activeTab,
                    ids: this.selectValueThree.join(','),
                    start_date: this.start_date,
                    end_date: this.end_date
                }
                const url = `statistics/panelData?${this.getParamByJson(params)}`
                fetch(this.baseurl + url, {
                    method: 'get',
                    headers: {...this.headers}
                }).then(res => res.text()).then(async res => {
                    const resData = JSON.parse(res)
                    if (resData.code === 0) {
                        this.ListData = resData.data
                        this.totalData.frozen_bal = resData.data.max_frozen_total
                        this.totalData.upl = resData.data.upl_total
                        this.totalData.profit = resData.data.pnl_total
                        this.myChart.clear()
                        this.lineEchart.clear()
                        await this.getLineEchart()
                        await this.getLine2Echart()
                    } else {
                        this.$message.error(resData.msg)
                    }
                }).catch(err => {
                    this.$message(err)
                }).finally(() => {
                    this.loading.close()
                })
            },
            /**
             * 获取所有账号
             */
            async getAccountList() {
                const url = `account/select?page=1&limit=50`
                fetch(this.baseurl + url, {
                    method: 'get',
                    headers: {...this.headers}
                }).then(res => res.text()).then(async res => {
                    const resData = JSON.parse(res)
                    if (resData.code === 0) {
                        resData.data.forEach((item) => {
                            this.totalData.eq += parseFloat(item.eq)
                            const obj = {label: item.title, key: item.id}
                            this.allAccount.push(obj)
                        })
                        await this.init()
                    } else {
                        this.$message.error(resData.msg)
                    }
                }).catch(err => {
                    this.$message(err)
                })
            },
            /**
             * 获取所有的模型
             */
            async getModelList() {
                const url = `trade-model/select`
                fetch(this.baseurl + url, {
                    method: 'get',
                    headers: {...this.headers}
                }).then(res => res.text()).then(async res => {
                    const resData = JSON.parse(res)
                    if (resData.code === 0) {
                        resData.data.forEach((item) => {
                            this.allModel.push({label: item.name, key: item.id})
                        })
                    } else {
                        this.$message.error(resData.msg)
                    }
                }).catch(err => {
                    this.$message(err)
                })
            },
            async init() {
                this.selectValueTwo = this.selectOptionTwo[0].key
                this.handleTwoChange(this.selectOptionTwo[0].key)
                // this.selectValueThree = this.allAccount.map(item => item.key) // 默认选中所有账号
                this.selectValueThree = [this.allAccount[0].key]
                this.value1 = [moment().subtract(30, 'days').format('yyyy-MM-DD HH:mm:ss'), moment().format('yyyy-MM-DD HH:mm:ss')]
                this.value2 = [moment().subtract(12, "months").format('yyyy-MM-DD HH:mm:ss'), moment().format('yyyy-MM-DD HH:mm:ss')]
                this.handleRangeChange(this.value1)
            },
            // 折线图（未实现收益、收益数据、回撤数据、资金数据）
            getLineEchart() {
                const option = JSON.parse(JSON.stringify(this.option))
                option.color = this.color.map(item => item[0])
                option.xAxis[0].data = this.ListData.xAxis
                option.legend.data = this.ListData.series.map(item => item.name)
                option.yAxis[0].name = this.selectOptionOne.filter(item => item.key === this.selectValueOne)[0].label
                const list = []
                this.ListData.series.forEach((item, index) => {
                    const obj = {
                        name: item.name,
                        type: 'line',
                        smooth: true,
                        data: item[this.selectValueOne]
                    }
                    list.push(obj)
                })
                option.series = list
                this.myChart.setOption(option)
            },
            getLine2Echart() {
                const option = JSON.parse(JSON.stringify(this.option))
                option.color = this.color.map(item => item[0])
                option.xAxis[0].data = this.ListData.xAxis
                option.legend.data = this.ListData.series.map(item => item.name)
                option.yAxis[0].name = '最大占用数据'
                const list = []
                this.ListData.series.forEach((item, index) => {
                    const obj = {
                        name: item.name,
                        type: 'line',
                        smooth: true,
                        data: item.max_frozen_data
                    }
                    list.push(obj)
                })
                option.series = list
                this.lineEchart.setOption(option)
            },
            // 时间tab改变事件
            handleTabChange(value) {
                this.activeTab = value.key
                if (value.key === 1) {
                    this.start_date = this.value1[0]
                    this.end_date = this.value1[1]
                } else {
                    this.start_date = moment(this.value2[0]).endOf("month").format("YYYY-MM-DD") + ' 00:00:00'
                    this.end_date = moment(this.value2[1]).endOf("month").format("YYYY-MM-DD") + ' 00:00:00'
                }
                this.getPanelData()
            },
            // 日期选择change
            handleRangeChange(data) {
                this.start_date = data[0]
                this.end_date = data[1]
                this.getPanelData()
            },
            // 月份选择change
            handleMonthChange(data) {
                this.start_date = moment(data[0]).endOf("month").format("YYYY-MM-DD") + ' 00:00:00'
                this.end_date = moment(data[1]).endOf("month").format("YYYY-MM-DD") + ' 00:00:00'
                this.getPanelData()
            },
            // 收益、回撤change
            handleOneChange(data) {
                this.getLineEchart()
                this.getLine2Echart()
            },
            // 账号、模型change
            handleTwoChange(data) {
                // 清空
                this.selectOptionThree = []
                this.selectValueThree = ''
                // 面板类型 1-账号 2-模型
                if (data === 1) {
                    this.selectOptionThree = this.allAccount
                } else if (data === 2) {
                    this.selectOptionThree = this.allModel
                }
            },
            // 具体账号、具体模型change
            handleThreeChange(data) {
                this.getPanelData()
            },
            // 将json转为get参数
            getParamByJson(json) {
                return Object.keys(json).map(function (key) {
                    return encodeURIComponent(key) + "=" + encodeURIComponent(json[key]);
                }).join("&");
            }
        }
    })
</script>
